#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/completion.h>
#include <linux/signal.h>

static struct task_struct * slam1, * slam2;
static struct completion slam_comp;

static int exit_flag = 0;

extern unsigned long msleep_interruptible(unsigned int msecs);

static int slam1_func(void *data)
{
	do{
		printk("I'm in slam1,wating slam_comp completion!\n");
		wait_for_completion(&slam_comp);
		printk("slam1:slam_comp completion done!\n");
	}while(!exit_flag);

	return 0;
}

static int slam2_func(void *data)
{
	int i = 0;
	do{
		printk("I'm in slam2_func,i'll do complete!\n");
		i++;
		if(i%2 == 0){
			complete(&slam_comp);
			i=0;
		}
		msleep_interruptible(5000);
	}while(!exit_flag);

	return 0;
}

static __init int kthread_completion_init(void)
{
	init_completion(&slam_comp);

	slam1 = kthread_run(slam1_func, NULL, "slam1");
	if(IS_ERR(slam1))
	{
		printk("kthread_run slam1 failed!\n");
		return 1;
	}

	slam2 = kthread_run(slam2_func, NULL, "slam2");
	if(IS_ERR(slam2))
	{
		printk("kthread_run slam2 failed!\n");
		return 1;
	}

	return 0;
}

static __exit void kthread_completion_exit(void)
{
	exit_flag = 1;
	complete_all(&slam_comp);

	if(!IS_ERR(slam1))
	      kthread_stop(slam1);

	if(!IS_ERR(slam2))
	      kthread_stop(slam2);
}

module_init(kthread_completion_init);
module_exit(kthread_completion_exit);
